<script setup>

// 水波纹按钮组件

import {ref} from 'vue';

// 存储所有活动波纹对象的响应式数组，每个波纹对象包含位置、尺寸和透明度属性
const ripples = ref([])
// 自增计数器，确保每个波纹都有唯一ID
let rippleCount = 0
// 存储浏览器动画帧ID，用于后续取消动画
let animationId

// 鼠标按下时触发
const startRipples = (event) => {
  // 获取按钮的边界矩形
  const button = event.currentTarget
  const rect = button.getBoundingClientRect()
  // 计算波纹最大尺寸（取按钮宽高的最大值）
  const size = Math.max(rect.width, rect.height)
  // 计算波纹中心坐标
  const x = rect.right - rect.left - size / 2
  const y = rect.bottom - rect.top - size / 2

  // 创建波纹对象
  const createRipple = () => {
    ripples.value.push({
      id: rippleCount++, // 唯一ID
      x, // X坐标
      y, // Y坐标
      size: 0, // 初始尺寸
      opacity: 0.5 // 初始透明度
    })
    // 限制最大波纹数量为3
    if (ripples.value.length > 3) {
      // 移除最早创建的波纹
      ripples.value.shift()
    }
  }

  // 动画循环
  const animate = () => {
    ripples.value.forEach(ripple => {
      // 尺寸线性增长
      ripple.size += 2
      // 透明度递减
      ripple.opacity -= 0.01
    })

    // 过滤掉透明度<=0的波纹
    ripples.value = ripples.value.filter(ripple => ripple.opacity > 0)
    // 补充新波纹
    if (ripples.value.length < 3) {
      createRipple()
    }

    // 请求下一帧动画（形成递归循环）
    // requestAnimationFrame 是浏览器提供的专门用于优化动画性能的 API
    animationId = requestAnimationFrame(animate)
  }
  createRipple()
  animate()
}

// 鼠标释放/移出时触发
const stopRipples = () => {
  // 取消动画帧
  cancelAnimationFrame(animationId)
  // 清空所有波纹
  ripples.value = []
}

// 生成波纹样式
const getRippleStyle = (ripple) => ({
  left: `${ripple.x}px`, // X位置
  top: `${ripple.y}px`, // Y位置
  width: `${ripple.size}px`, // 当前尺寸
  height: `${ripple.size}px`, // 保持圆形
  opacity: ripple.opacity // 当前透明度
})

</script>

<template>
  <!--
    @mousedown：鼠标按下时触发波纹动画
    @mouseup：鼠标释放时停止动画
    @mouseleave：鼠标移出按钮区域时停止动画
   -->
  <button class="ripple-button" @mousedown="startRipples" @mouseup="stopRipples" @mouseleave="stopRipples">
    <slot></slot>
    <!-- 动态生成多个波纹元素，但限制最多3个（ripples.value.length > 3 时移除旧波纹） -->
    <span v-for="ripple in ripples" :key="ripple.id" class="ripple" :style="getRippleStyle(ripple)"></span>
  </button>
</template>

<style scoped lang="stylus">
.ripple-button {
  position: relative; // 相对定位（用于波纹绝对定位）
  overflow: hidden; // 隐藏超出按钮范围的波纹
  border: none; // 去除默认边框
  background none; // 去除默认背景
  color: white; // 文字颜色
  cursor: pointer; // 鼠标手势
  border-radius: 50%; // 圆形按钮
  outline: none; // 去除聚焦轮廓
  margin 0 // 清除默认外边距
  padding 0 // 清除默认内边距
}

.ripple {
  position: absolute; // 绝对定位
  border-radius: 50%; // 圆形波纹
  background-color: rgba(255, 255, 255, 0.7); // 半透明白色
  transform: translate(-50%, -50%); // 中心点对齐
  pointer-events: none; // 禁止鼠标事件穿透
}
</style>